#include "Triangle.hpp"
#include "OBJ_Loader.hpp"

__device__ bool Triangle::intersect(const Ray &ray) { return true; }
__device__ bool Triangle::intersect(const Ray &ray, float &tnear,
                                    uint32_t &index) const
{
    return false;
}

__device__ Bounds3 Triangle::getBounds()
{
    return Union(Bounds3(v0, v1), v2);
}

Bounds3 Triangle::getBounds(bool isFromHost)
{
    assert(isFromHost);
    return Union(Bounds3(v0, v1, true), v2, true);
}

__device__ Vector3fDev Triangle::evalDiffuseColor(const Vector2fDev &) const
{
    return Vector3fDev(0.5, 0.5, 0.5);
}

MeshTriangle::MeshTriangle(const std::string &filename, Material *mt) : Object(1)
{
#define OBJECT_MAX_SELF_NUM 64
    objl::Loader loader;
    loader.LoadFile(filename);

    area = 0;
    m = mt;
    assert(loader.LoadedMeshes.size() == 1);
    auto mesh = loader.LoadedMeshes[0];
    Vector3fDev min_vert = Vector3fDev{102400.F,
                                       102400.F,
                                       102400.F, true};
    Vector3fDev max_vert = Vector3fDev{-102400.F,
                                       -102400.F,
                                       -102400.F, true};

    for (int i = 0; i < mesh.Vertices.size(); i += 3)
    {
        std::array<Vector3fDev, 3> face_vertices;

        for (int j = 0; j < 3; j++)
        {
            auto vert = Vector3fDev(mesh.Vertices[i + j].Position.X,
                                    mesh.Vertices[i + j].Position.Y,
                                    mesh.Vertices[i + j].Position.Z, true);
            face_vertices[j] = vert;

            min_vert = Vector3fDev(host_min(min_vert.x, vert.x),
                                   host_min(min_vert.y, vert.y),
                                   host_min(min_vert.z, vert.z), true);
            max_vert = Vector3fDev(host_max(max_vert.x, vert.x),
                                   host_max(max_vert.y, vert.y),
                                   host_max(max_vert.z, vert.z), true);
        }
        triangles.push_back(new Triangle(face_vertices[0], face_vertices[1],
                                         face_vertices[2], mt));
    }
    bounding_box = Bounds3(min_vert, max_vert, true);

    Object *objects_ptr[OBJECT_MAX_SELF_NUM];
    int objs_num = 0;

    for (auto tri : triangles)
    {
        objects_ptr[objs_num++] = tri;
        area += tri->area;
    }
    bvh = new BVHAccel(objects_ptr, objs_num);
}